import axios from 'axios';
import { clean } from './utils';
import { message } from 'antd';
import type {
  RequestOptionsInit,
  RequestOptionsWithoutResponse,
  RequestMethod,
  RequestOptionsWithResponse,
  RequestResponse,
  Context,
  CancelTokenStatic,
  CancelStatic,
} from 'umi-request';
import initRequest, { extend } from 'umi-request';

import type { AxiosRequestConfig } from 'axios';
import { FROM_URL_KEY, getToken, TOKEN_KEY } from './auth';
// import { AUTH_TOKEN_KEY, FROM_URL_KEY } from '@/common/constants';

// type ApapterEnum = 'davinci' | 'cys';
// type ApapterEnum = 'cys';

export const headUrl = '/api';

type ErrorType = {
  message?: string;
  code?: number;
};

// type AdapterItem = {
//   interceptor: any;
//   middleware: any;
// };

// type AdapterMap = Record<ApapterEnum, AdapterItem>;

interface RequestExtendOptions {
  // adapter?: ApapterEnum;
  disabledErrMsg?: boolean;
}

// export const TOKEN_KEY = AUTH_TOKEN_KEY;
const codeMessage = {
  200: '服务器成功返回请求的数据。',
  201: '新建或修改数据成功。',
  202: '一个请求已经进入后台排队（异步任务）。',
  204: '删除数据成功。',
  400: '发出的请求有错误，服务器没有进行新建或修改数据的操作。',
  401: '用户没有权限（令牌、用户名、密码错误）。',
  403: '用户得到授权，但是访问是被禁止的。',
  404: '发出的请求针对的是不存在的记录，服务器没有进行操作。',
  405: '请求方法不被允许。',
  406: '请求的格式不可得。',
  410: '请求的资源被永久删除，且不会再得到的。',
  422: '当创建一个对象时，发生一个验证错误。',
  500: '服务器发生错误，请检查服务器。',
  502: '网关错误。',
  503: '服务不可用，服务器暂时过载或维护。',
  504: '网关超时。',
};

/**
 * 异常处理程序
 */
const defaultErrorHandler = (response: Response, errMsg: string, options: RequestOptionsInit) => {
  let error: ErrorType = {};
  const defaultErrMsg = '网络发生异常，无法连接服务器。';
  if (response?.status === 200) {
    return response;
  }

  if (response?.status !== 200) {
    const errorText =
      errMsg || codeMessage[response.status] || response.statusText || defaultErrMsg;
    const { status } = response;
    error = {
      message: errorText,
      code: status,
    };
  }

  if (!response) {
    error = {
      message: defaultErrMsg,
      code: 504,
    };
  }
  // @ts-ignore
  if (options.disabledErrMsg !== true) {
    message.error(error.message);
  }
  // eslint-disable-next-line @typescript-eslint/no-throw-literal
  throw error;
};

const cysAdapter = {
  interceptor: async (response: Response, options: RequestOptionsInit) => {
    const data: Result<any> = await response.clone().json();
    defaultErrorHandler(response, data?.msg || '', options);
    if (data?.code !== '0') {
      const error = {
        message: data?.msg,
        code: data?.code,
      };
      // @ts-ignore
      if (options.disabledErrMsg !== true) {
        message.error(error.message);
      }
      // eslint-disable-next-line @typescript-eslint/no-throw-literal
      throw error;
    }
    return response;
  },
  middleware(ctx: Context) {
    // umi-request的拦截器一定要返回response, 所以后台数据的处理需要放在中间件中
    ctx.res = ctx.res?.data;
    return ctx;
  },
};

// const ADAPTER_MAP: AdapterMap = {
//   davinci: davinciAdapter,
//   cys: cysAdapter,
// };

const requestInterceptor = (url: string, options: RequestOptionsInit) => {
  const headers: any = {};
  // const token = localStorage.getItem(TOKEN_KEY);
  const token = getToken();
  if (token) {
    headers.Authorization = `${token}`;
  }
  const reqOptions = { ...options };

  // if (reqOptions.headers?.noCleanData !== 'true') {
  //   if (reqOptions.data) {
  //     clean(reqOptions.data);
  //   }
  //   if (reqOptions.params) {
  //     clean(reqOptions.params);
  //   }
  // } else {
  //   delete reqOptions.headers?.noCleanData;
  // }

  let newUrl = headUrl + url;
  // if (url.includes('http')) {
  //   newUrl = url;
  // } else if (url.includes('/rewirte')) {
  //   newUrl = url.replace('/rewirte', '');
  // } else {
  //   newUrl = headUrl + url;
  // }

  return {
    url: newUrl,
    options: { ...reqOptions, headers: { ...reqOptions.headers, ...headers } },
  };
};

const responseInterceptor = async (response: Response, options: RequestOptionsInit) => {
  // const redirect = response.headers.get('redirect'); // 若HEADER中含有REDIRECT说明后端想重定向
  // if (redirect === 'REDIRECT') {
  //   localStorage.removeItem(TOKEN_KEY);
  //   let win: any = window;
  //   while (win !== win.top) {
  //     win = win.top;
  //   }

  //   localStorage.setItem(FROM_URL_KEY, win.location.href);
  //   // 将后端重定向的地址取出来,使用win.location.href去实现重定向的要求
  //   const contextpath = response.headers.get('contextpath');
  //   win.location.href = contextpath?.replace(
  //     /redirect_uri=.*/,
  //     `redirect_uri=${win.location.href}`,
  //   );
  //   // /* const { pathname } = history.location;
  //   // history.replace({
  //   //   pathname: '/login',
  //   //   search: stringify({
  //   //     redirect: pathname,
  //   //   }),
  //   // }); */
  // }
  // @ts-ignore
  // const adapter = ADAPTER_MAP[`${options.adapter}`];
  // if (adapter && adapter.interceptor) {
  //   return adapter.interceptor(response, options);
  // }
  // cysAdapter.interceptor(response, options);

  // const data: Result<any> = await response.clone().json();
  // defaultErrorHandler(response, data?.msg || '', options);
  // if (data?.code !== '0') {
  //   const error = {
  //     message: data?.msg,
  //     code: data?.code,
  //   };
  //   // @ts-ignore
  //   if (options.disabledErrMsg !== true) {
  //     message.error(error.message);
  //   }
  //   // eslint-disable-next-line @typescript-eslint/no-throw-literal
  //   throw error;
  // }
  // return response;
  return response;
};

let requestMethodInstance: RequestMethod;
const getRequestMethod = () => {
  if (requestMethodInstance) {
    return requestMethodInstance;
  }
  requestMethodInstance = extend({});
  const requestInterceptors = [requestInterceptor];
  const responseInterceptors = [responseInterceptor];
  requestMethodInstance.use(async (ctx, next) => {
    await next();
    cysAdapter.middleware(ctx);
  });
  requestInterceptors.map((ri) => requestMethodInstance.interceptors.request.use(ri));
  responseInterceptors.map((ri) => requestMethodInstance.interceptors.response.use(ri));
  return requestMethodInstance;
};

const requestMethod = getRequestMethod();
interface RequestMethodInUmi<R = false> {
  <T = any>(url: string, options: RequestOptionsWithResponse & RequestExtendOptions): Promise<
    RequestResponse<T>
  >;
  <T = any>(url: string, options: RequestOptionsWithoutResponse & RequestExtendOptions): Promise<T>;
  <T = any>(url: string, options?: RequestOptionsInit & RequestExtendOptions): R extends true
    ? Promise<RequestResponse<T>>
    : Promise<T>;
  get: RequestMethodInUmi<R>;
  post: RequestMethodInUmi<R>;
  delete: RequestMethodInUmi<R>;
  put: RequestMethodInUmi<R>;
  patch: RequestMethodInUmi<R>;
  head: RequestMethodInUmi<R>;
  options: RequestMethodInUmi<R>;
  rpc: RequestMethodInUmi<R>;
  Cancel: CancelStatic;
  CancelToken: CancelTokenStatic;
  isCancel: (value: any) => boolean;
}
// @ts-ignore
const tRequest: RequestMethodInUmi = (url: any, options: any) => {
  return requestMethod(url, options);
};
const METHODS = ['get', 'post', 'delete', 'put', 'patch', 'head', 'options', 'rpc'];
METHODS.forEach((method) => {
  tRequest[method] = (url: any, options: any) => {
    return requestMethod(url, {
      ...options,
      method,
    });
  };
});
tRequest.Cancel = requestMethod.Cancel;
tRequest.CancelToken = requestMethod.CancelToken;
tRequest.isCancel = requestMethod.isCancel;

export default tRequest;

export const umiRequest = {
  requestInterceptors: [requestInterceptor],
  responseInterceptors: [responseInterceptor],
};

export async function request(data: any, config: AxiosRequestConfig): Promise<any> {
  const { url, ...rest } = config;
  const umiConfig: any = {
    ...rest,
  };
  if (umiConfig.method === 'post') {
    umiConfig.data = data;
  } else {
    umiConfig.params = data;
  }
  return initRequest(url as string, umiConfig);
}

interface DownloadCosFileParams {
  cosPath?: string;
  fileName: string;
  blobType: string;
  url?: string;
}

/**
 * 接口 /cos/downloadFile 下载封装
 */
export async function downloadCosFile({ cosPath, fileName, blobType, url }: DownloadCosFileParams) {
  const res = await axios.request({
    method: 'get',
    url: url || '/api/cos/downloadFile',
    params: { cosPath },
    headers: {
      Authorization: getToken(),
      appId: 1, // 替换成对应的appid，后端用来鉴权用
    },
    responseType: 'blob',
  });
  const blob = res.data;
  const link = document.createElement('a');
  link.href = URL.createObjectURL(new Blob([blob], { type: blobType }));
  link.download = fileName;
  document.body.appendChild(link);
  link.click();
  URL.revokeObjectURL(link.href);
  document.body.removeChild(link);
}

/**
 * 导出数据
 */
export async function exportData(url: string, data: any, fileName?: string) {
  const res = await axios.request({
    method: 'POST',
    url,
    data,
    headers: {
      Authorization: 'Bearer ' + getToken(),
    },
    responseType: 'blob',
  });
  const blob = res.data;
  const link = document.createElement('a');
  link.href = URL.createObjectURL(new Blob([blob], { type: 'application/vnd.ms-excel' }));
  link.download = fileName || '';
  document.body.appendChild(link);
  link.click();
  URL.revokeObjectURL(link.href);
  document.body.removeChild(link);
}
